﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Windows.Forms;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using Noris.Schedule.UI;

namespace Noris.Tools.DbManager.Components
{
    public class DragBar : Noris.Schedule.UI.Components.DblGraphPanel, ICurrentRenderStyle
	{
		#region Konstrukce, interní eventy
		public DragBar()
		{
            this.MovingInit();
			this.MouseDown += new MouseEventHandler(DragBar_MouseDown);
			this.MouseUp += new MouseEventHandler(DragBar_MouseUp);
			this.MouseEnter += new EventHandler(DragBar_MouseEnter);
			this.MouseLeave += new EventHandler(DragBar_MouseLeave);
			this.MouseMove += new MouseEventHandler(DragBar_MouseMove);
		}

		void DragBar_MouseEnter(object sender, EventArgs e)
		{
			this.CurrentMouseState = MouseState.OnControl;
		}
		void DragBar_MouseLeave(object sender, EventArgs e)
		{
			this.CurrentMouseState = MouseState.Outside;
		}

		void DragBar_MouseMove(object sender, MouseEventArgs e)
		{
            if (this.CurrentMoveState == MoveState.WaitInFender)
            {
                if (this._MouseIsOutOfFender(e.Location))
                {
                    this.CurrentMoveState = MoveState.Moving;
                    this.Cursor = Cursors.NoMove2D;
                }
            }
            if (this.CurrentMoveState == MoveState.Moving)
                this._DragByMouse(e);

		}

        private bool _MouseIsOutOfFender(Point point)
        {
            return !this.MouseFender.Contains(point);
        }

        private void _DragByMouse(MouseEventArgs e)
        {
            Point mousePosition = Control.MousePosition;
            Point movedLocation = mousePosition.GetRelativePointFromBase(this.MouseDownOffset);
            this.Location = movedLocation;
        }
        void DragBar_MouseDown(object sender, MouseEventArgs e)
		{
			if (e.Button == System.Windows.Forms.MouseButtons.Left)
                this.MoveMouseDownLeftButton(e);
			else if (e.Button == System.Windows.Forms.MouseButtons.Right)
                this.MoveMouseDownRightButton(e);
		}

		void DragBar_MouseUp(object sender, MouseEventArgs e)
		{
            if (this.CurrentMoveState != MoveState.None)
            {
                this.CurrentMoveState = MoveState.None;
                this.Cursor = Cursors.Default;
            }
			this.CurrentMouseState = MouseState.OnControl;
		}
		#endregion
		#region Řízení pohybu (tažení myší) - move a resize
        /// <summary>
        /// Iniciace pohybu (reset, v konstruktoru)
        /// </summary>
        protected virtual void MovingInit()
        {
            this.CurrentMoveFragment = MoveFragment.None;
            this.CurrentMouseState = MouseState.None;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="e"></param>
        protected virtual void MoveMouseDownLeftButton(MouseEventArgs e)
        {
            this.CurrentMouseState = MouseState.MouseLeftDown;

            this.MouseDownPoint = e.Location;
            this.MouseDownOffset = Control.MousePosition.GetRelativePointFromBase(this.Location);
            Size dragSize = SystemInformation.DragSize;
            Point dragOrig = new Point(this.MouseDownPoint.X - dragSize.Width / 2, this.MouseDownPoint.Y - dragSize.Height / 2);
            this.MouseFender = new Rectangle(dragOrig, dragSize);
            
            this.CurrentMoveState = MoveState.WaitInFender;
        }
        protected virtual void MoveMouseDownRightButton(MouseEventArgs e)
        {
            this.CurrentMouseState = MouseState.MouseRightDown;

            this.MouseDownPoint = e.Location;
            this.MouseDownOffset = Control.MousePosition.GetRelativePointFromBase(this.Location);
        }
        /// <summary>
        /// Informace o tom, co se právě posouvá.
        /// Změna aktualizuje kurzor.
        /// </summary>
        protected MoveFragment CurrentMoveFragment { get { return _CurrentMoveFragment; } set { _CurrentMoveFragment = value; RefreshCursor(); } }
        private MoveFragment _CurrentMoveFragment;
        /// <summary>
        /// Aktuální stav posouvání.
        /// Změna aktualizuje kurzor.
        /// </summary>
        protected MoveState CurrentMoveState { get { return _CurrentMoveState; } set { _CurrentMoveState = value; RefreshCursor(); } }
        private MoveState _CurrentMoveState;
        /// <summary>
        /// Bod, na kterém byla zmáčknuta myš. Bod je relativní k počátku this Controlu: levý horní roh = bod (0,0).
        /// </summary>
        protected Point MouseDownPoint { get; set; }
        /// <summary>
        /// Offset souřadnice myši (Control.MousePosition) v době, kde se stiskla myš, proti počátku this Controlu.
        /// </summary>
        protected Point MouseDownOffset { get; set; }
        /// <summary>
        /// Prostor (malá ohrádka), v němž se za stavu CurrentMoveState == MoveState.WaitInFender může pohybovat myš, aniž by došlo k překlopení do stavu MoveState.Moving.
        /// </summary>
        protected Rectangle MouseFender { get; set; }
		#endregion

		#region Cursor

        protected virtual void RefreshCursor()
        {
            
        }
        #endregion
        #region Property
        /// <summary>
		/// Posun barev v controlu
		/// </summary>
		[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
		[Category("Appearance")]
		[Description("Posun barev v controlu")]
		[RefreshProperties(System.ComponentModel.RefreshProperties.Repaint)]
		[NotifyParentProperty(true)]
		public int BackColorShift
		{
			get { return _BackColorShift; }
			set { _BackColorShift = (value < -200 ? -200 : (value > 200 ? 200 : value)); this.Draw(); }
		}
        /// <summary>
        /// Styl renderování tohoto controlu.
        /// Vložení hodnoty způsobí překreslení controlu.
        /// </summary>
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        [Category("Appearance")]
        [Description("Styl renderování tohoto controlu")]
        [RefreshProperties(System.ComponentModel.RefreshProperties.Repaint)]
        [NotifyParentProperty(true)]
        public RenderStyle RenderStyle
        {
            get { return _RenderStyle; }
            set { _RenderStyle = value; this.Draw(); }
        }
        /// <summary>
        /// Aktuální styl renderování tohoto controlu.
        /// Vyhodnocuje se hodnota this.RenderStyle, 
        /// a pokud je Inherited, tak se hledá v řetězci this.Parent takový Control, který je ICurrentRenderStyle, a převezme se jeho CurrentRenderStyle.
        /// </summary>
        public RenderStyle CurrentRenderStyle
        {
            get
            {
                RenderStyle style = this.RenderStyle;
                if (style == Components.RenderStyle.Inherited)
                {
                    Control parent = this.Parent;
                    while (parent != null)
                    {
                        if (parent is ICurrentRenderStyle)
                        {
                            style = (parent as ICurrentRenderStyle).CurrentRenderStyle;
                            break;
                        }
                        parent = parent.Parent;         // Podíváme se na parenta našeho parenta (tj. dědeček, pradědeček, až k Adamovi).
                    }
                }
                return style;
            }
        }
		/// <summary>
		/// V jakém stavu je control z hlediska přítomnosti myši.
        /// Vložení hodnoty způsobí překreslení controlu.
		/// </summary>
		[Browsable(false)]
		[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
		public MouseState CurrentMouseState
		{
			get { return this._CurrentMouseState; }
			protected set { this._CurrentMouseState = value; this.Draw(); }
		}
		protected int _BackColorShift = 25;
        protected RenderStyle _RenderStyle = RenderStyle.Inherited;
		protected MouseState _CurrentMouseState = MouseState.None;
		#endregion
		#region Paint
		protected override void OnPaintToBuffer(object sender, PaintEventArgs e)
		{
			// base.OnPaintToBuffer(sender, e);
			RectangleF r = this.ClientRectangle;
			Color root = this.BackColor;
			int shift = this.BackColorShift;
			using (LinearGradientBrush lgb = new LinearGradientBrush(r, root, root, 90f))
			{
                lgb.InterpolationColors = UiRenderer.GetColorBlend(this.BackColor, this.BackColorShift, this.CurrentRenderStyle, this.CurrentMouseState);
				e.Graphics.FillRectangle(lgb, r);




				/*
				if (false)
				{
					float xl = r.X;
					float xr = r.Right - 1f;
					float yt = r.Y;
					float yb = r.Bottom - 1f;
					float xw = (xr - xl);
					float yh = (yb - yt);
					float xa = (xw > 12f ? 6f : xw / 2f);
					float xc = xl + xw / 2f;
					float yc = yt + yh / 2f;
					float aw = 2f * xa;
					float ay = yh / 2f;

					GraphicsPath gp = new GraphicsPath();
					if (false)
					{	// Horní půlka s oblouky po stranách:
						gp.AddLine(xl, yt, xr, yt);
						gp.AddArc(xr - aw, yt - ay, aw, yh, 0f, 90f);
						gp.AddLine(xr - xa, yc, xl + xa, yc);
						gp.AddArc(xl, yt - ay, aw, yh, 90f, 90f);
					}
					if (true)
					{
						gp.AddLine(xl, yt, xr, yt);
						gp.AddLine(xr, yt, xr, yb);
						gp.AddArc(xr - aw, yt + ay, aw, yh, 0f, -90f);
						gp.AddLine(xr - xa, yc, xl + xa, yc);
						gp.AddArc(xl, yt + ay, aw, yh, -90f, -90f);
						gp.AddLine(xl, yb, xl, yt);
					}

					e.Graphics.FillPath(lgb, gp);
				}
				*/
			}
		}
		#endregion
        protected enum MoveFragment
        {
            None = 0,
            TopLeftPoint,
            TopEdge,
            TopRightPoint,
            RightEdge,
            BottomRightPoint,
            BottomEdge,
            BottomLeftPoint,
            LeftEdge,
            Body
        }
	}
    public enum MoveState
    {
        None = 0,
        WaitInFender,
        Moving
    }
   
}
